package com.wjm.core;

import com.wjm.http.HttpRequest;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

/**
 * Data:2022年08月03日
 * Author:wjm
 * Content:
 *
 *   负责与指定客户端HTTP交互
 *      该线程来与客户端交互的过程必须遵守HTTP协议要求，采取一问一答的方式进行，固定的解析步骤：
 *       1）解析请求【问】
 *       2）处理请求
 *       3）响应请求【答】
 *
 */
public class RequestHandle implements Runnable{
    //声明一个Socket变量
    private Socket socket;

    /**
     * 用来接收从WebServer传过来的socket，socket封装着每一个客户端发送过来的所有信息
     * @param socket 从WebServer传过来的socket
     */
    public RequestHandle(Socket socket){
        this.socket = socket;
    }


    @Override
    public void run() {
        //1.解析请求
        HttpRequest httpRequest= new HttpRequest(socket);

        //2.处理请求
        String url = httpRequest.getUrl();

        /*
            ./webapps/ 可以认为是一个存放所以资源的文件夹，当需要某个应用的资源文件时，就可以在webapps下面查找
            要求客户端在输入请求资源时，一并输入应用的名称，例如：
                  应用是找：myweb
                  资源是找：index.html
                  客户端发送的请求是：http://localhost:8080/myweb/index.html
        * */
        File file = new File("./webapps"+url);

        //判断资源是否存在，并且是否为文件夹
        if (file.exists() && file.isFile()){
            //如果是就将客户端所需的资源返回

            //3.响应请求

            /*
             * 做实体资源的响应
             *   （1）状态行
             *   （2）响应头
             *   （3）响应正文
             * */
            try {
                //获取字节输出流
                OutputStream out = socket.getOutputStream();
                //状态行
                String line = "Http/1.1 200 ok";
                //将字符串转为字节数组
                byte[] bytes = line.getBytes("ISO8859-1");
                out.write(bytes);
                //状态行的结束是以两个连续的字符作为标识[CRLF]
                out.write(13); //CR
                out.write(10); //LF

                //响应头
                line = "Content-Type: text/html";
                //将字符串转为字节数组
                bytes = line.getBytes("ISO8859-1");
                out.write(bytes);
                //响应头一行的结束是以两个连续的字符作为标识[CRLF]
                out.write(13); //CR
                out.write(10); //LF

                line = "Content-Length: "+file.length();
                //将字符串转为字节数组
                bytes = line.getBytes("ISO8859-1");
                out.write(bytes);
                //响应头一行的结束是以两个连续的字符作为标识[CRLF]
                out.write(13); //CR
                out.write(10); //LF

                //响应头全部发送结束，是以单独的连续的两个字符作为标识
                out.write(13); //CR
                out.write(10); //LF

                //响应正文
                //创建字节输入流对象读取，所需文件内容
                FileInputStream fileInputStream = new FileInputStream(file);
                //创建一个读取文件的字节数组
                byte[] bytes1 = new byte[5*1024];
                int len;
                while ((len = fileInputStream.read(bytes1)) != -1){
                    //将读取到的内容写出
                    /*
                     * 因为只有字节数组bytes1装满的才会写出，所以为了解决这个问题，我们需要用重载的write方法
                     * 当用字节数组来读取文件时，len其实表示的就是字节数组bytes1的长度
                     * */
                    out.write(bytes1,0,len);
                }
                System.out.println("数据响应完毕！");


            } catch (IOException e) {
                e.printStackTrace();
            }
        }else {
            //如果不符合则返回404页面
            file = new File("./webapps/commons/404.html");
            //3.响应请求

            //获取需要响应的文件对象
            //File file = new File("./webapps/myweb/index.html");
            /*
             * 做实体资源的响应
             *   （1）状态行
             *   （2）响应头
             *   （3）响应正文
             * */
            try {
                //获取字节输出流
                OutputStream out = socket.getOutputStream();
                //状态行
                String line = "Http/1.1 200 ok";
                //将字符串转为字节数组
                byte[] bytes = line.getBytes("ISO8859-1");
                out.write(bytes);
                //状态行的结束是以两个连续的字符作为标识[CRLF]
                out.write(13); //CR
                out.write(10); //LF

                //响应头
                line = "Content-Type: text/html";
                //将字符串转为字节数组
                bytes = line.getBytes("ISO8859-1");
                out.write(bytes);
                //响应头一行的结束是以两个连续的字符作为标识[CRLF]
                out.write(13); //CR
                out.write(10); //LF

                line = "Content-Length: "+file.length();
                //将字符串转为字节数组
                bytes = line.getBytes("ISO8859-1");
                out.write(bytes);
                //响应头一行的结束是以两个连续的字符作为标识[CRLF]
                out.write(13); //CR
                out.write(10); //LF

                //响应头全部发送结束，是以单独的连续的两个字符作为标识
                out.write(13); //CR
                out.write(10); //LF

                //响应正文
                //创建字节输入流对象读取，所需文件内容
                FileInputStream fileInputStream = new FileInputStream(file);
                //创建一个读取文件的字节数组
                byte[] bytes1 = new byte[5*1024];
                int len;
                while ((len = fileInputStream.read(bytes1)) != -1){
                    //将读取到的内容写出
                    /*
                     * 因为只有字节数组bytes1装满的才会写出，所以为了解决这个问题，我们需要用重载的write方法
                     * 当用字节数组来读取文件时，len其实表示的就是字节数组bytes1的长度
                     * */
                    out.write(bytes1,0,len);
                }
                System.out.println("404页面数据响应完毕！");


            } catch (IOException e) {
                e.printStackTrace();
            }
        }




    }






}
